---
title: Search
description: Understanding search in Airweave
edit-this-page-url: https://github.com/airweave-ai/airweave/blob/main/fern/docs/pages/search.mdx
slug: search
---

<Warning>
**Search API Updated (October 2025)**

The search API has been updated. The legacy API continues to work, but we recommend migrating to the new API.

<Accordion title="View Migration Details">

### What Changed?

**Endpoints:**
- ~~`GET /collections/{id}/search`~~ → Still works but deprecated
- `POST /collections/{id}/search` → Accepts both old and new schemas

**Request Schema:**
| Legacy Field | New Field | Change |
|-------------|-----------|--------|
| `response_type` (`"raw"` \| `"completion"`) | `generate_answer` (boolean) | Enum → Boolean |
| `expansion_strategy` (`"auto"` \| `"llm"` \| `"no_expansion"`) | `expand_query` (boolean) | Enum → Boolean |
| `enable_query_interpretation` | `interpret_filters` | Renamed |
| `search_method` | `retrieval_strategy` | Renamed |
| `recency_bias` | `temporal_relevance` | Renamed |
| `enable_reranking` | `rerank` | Renamed |
| `score_threshold` | *(removed)* | Deprecated |

### Full Comparison

<CodeGroup>
```python title="Legacy (Deprecated)"
from airweave import AirweaveSDK

client = AirweaveSDK(api_key="YOUR_API_KEY")

# Old GET endpoint with query params
response = await client.collections.search_collection(
    readable_id="my-collection",
    query="customer issues",
    response_type="completion",  # ❌
    limit=50,
    recency_bias=0.5,
)

# Old POST with verbose schema
from airweave.schemas.search import SearchRequest

request = SearchRequest(
    query="deployment procedures",
    response_type="completion",           # ❌
    expansion_strategy="auto",            # ❌
    enable_reranking=True,                # ✅
    enable_query_interpretation=True,     # ❌
    search_method="hybrid",               # ❌
    recency_bias=0.3,                     # ❌
)
```

```python title="New (Recommended)"
from airweave import AirweaveSDK

client = AirweaveSDK(api_key="YOUR_API_KEY")

# New POST-only endpoint with clean schema
from airweave.schemas.search import SearchRequest

request = SearchRequest(
    query="customer issues",
    generate_answer=True,         # ✅
    limit=50,
    temporal_relevance=0.5,       # ✅
)

response = await client.collections.search_collection(
    readable_id="my-collection",
    search_request=request
)

# Comprehensive example
request = SearchRequest(
    query="deployment procedures",
    generate_answer=True,         # ✅
    expand_query=True,            # ✅
    rerank=True,                  # ✅
    interpret_filters=True,       # ✅
    retrieval_strategy="hybrid",  # ✅
    temporal_relevance=0.3,       # ✅
)
```
</CodeGroup>


## Migration Steps

### Step 1: Update Request Schema

<CodeGroup>
```python title="Before"
request = SearchRequest(
    query="test",
    response_type="completion",
    expansion_strategy="auto",
    enable_reranking=True,
    search_method="hybrid",
)
```

```python title="After"
request = SearchRequest(
    query="test",
    generate_answer=True,
    expand_query=True,
    rerank=True,
    retrieval_strategy="hybrid",
)
```
</CodeGroup>

### Step 2: Update Response Handling

<CodeGroup>
```python title="Before"
response = await client.collections.search_collection(...)

# Old response structure
if response.status == "success":
    if response.response_type == "completion":
        print(response.completion)
    else:
        print(response.results)
```

```python title="After"
response = await client.collections.search_collection(...)

# New response structure
if response.completion:
    print(response.completion)
else:
    print(response.results)
```
</CodeGroup>

### Step 3: Remove Deprecated Fields

The new response no longer includes:
- `status` field
- `response_type` field

## REST API Migration

### GET Endpoint (Deprecated)

<CodeGroup>
```bash title="Legacy GET (Deprecated)"
curl -X GET "https://api.airweave.ai/collections/{id}/search?query=test&response_type=completion" \
  -H "x-api-key: your-api-key"
```

```bash title="New POST (Recommended)"
curl -X POST "https://api.airweave.ai/collections/{id}/search" \
  -H "x-api-key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "test",
    "generate_answer": true
  }'
```
</CodeGroup>

### POST Endpoint Schema

<CodeGroup>
```bash title="❌ Legacy Schema"
{
  "query": "test",
  "response_type": "completion",
  "expansion_strategy": "auto",
  "enable_reranking": true,
  "search_method": "hybrid"
}
```

```bash title="✅ New Schema"
{
  "query": "test",
  "generate_answer": true,
  "expand_query": true,
  "rerank": true,
  "retrieval_strategy": "hybrid"
}
```
</CodeGroup>


### Detecting Deprecation

When using the legacy API, you'll receive HTTP headers indicating deprecation:

```http
X-API-Deprecation: true
X-API-Deprecation-Message: ...
```

</Accordion>
</Warning>

Airweave lets you search across all your connected data sources through one unified interface. When you query a collection, Airweave runs a multi-step search pipeline that combines AI understanding with keyword precision. You can start with the defaults or configure each step for full control.

<Note>
Want to try out our search right now? Head to our [interactive API documentation](https://docs.airweave.ai/api-reference/collections/search-collections-readable-id-search-post) where you can test search queries directly in your browser!
</Note>

## Quick Reference

Here are the default settings Airweave uses. You can override any of these in your queries.

| Parameter | Default | Description |
|-----------|---------|-------------|
| `expand_query` | `true` | Generate query variations for better recall |
| `retrieval_strategy` | `hybrid` | Combines AI semantic search with keyword matching |
| `interpret_filters` | `false` | Extract filters from natural language (you control manually by default) |
| `rerank` | `true` | LLM-based result reordering (adds ~10s latency) |
| `temporal_relevance` | `0.3` | Weight toward recent content (0.0-1.0) |
| `generate_answer` | `true` | Generate AI completion from results |
| `limit` | `1000` | Maximum results to return |
| `offset` | `0` | Results to skip for pagination |

## Which endpoint to use

<CardGroup cols={2}>
  <Card title="Simple Search (Deprecated)" icon="magnifying-glass" href="/api-reference/collections/search-collections-readable-id-search-get">
    **GET** `/collections/{readable_id}/search`

    **⚠️ Deprecated:** This endpoint is maintained for backwards compatibility only. Use POST for new integrations.
  </Card>

  <Card title="Advanced Search (Recommended)" icon="sliders" href="/api-reference/collections/search-collections-readable-id-search-post">
    **POST** `/collections/{readable_id}/search`

    **Recommended:** Full control. Use this for all new integrations.
  </Card>
</CardGroup>

## How Airweave search works

Each search runs through a multi step pipeline. Understanding the stages helps explain why different parameters exist and when to use them:

1. **Query expansion**: Generate variations of the user query to capture synonyms and related terms.
2. **Retrieval**: Use keyword, neural, or hybrid methods to fetch candidate documents.
3. **Filtering**: Apply structured metadata filters before or during retrieval.
4. **Recency bias**: Optionally weight results toward fresher content.
5. **Reranking**: Use AI to reorder the top results for higher precision.
6. **Answer generation**: Return raw documents or synthesize a natural language response.

Defaults are designed to work out of the box, and you can override any stage as needed.

## Parameters
### Query Expansion

Expands your query to catch related terms and synonyms that may not appear verbatim in your documents. This improves recall when wording differs but meaning is the same.

**Parameter**: `expand_query` (boolean)
- `true` (default): Generate query variations for better recall
- `false`: Search only for your exact query

<CodeBlocks>
```bash title="cURL" {6}
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "customer churn analysis",
    "expand_query": true
  }'
```

```python title="Python" {9}
from airweave import AirweaveSDK

client = AirweaveSDK(api_key="YOUR_API_KEY")

results = await client.collections.search_advanced(
    "your-collection-id",
    {
        "query": "customer churn analysis",
        "expand_query": true
    }
)
```

```javascript title="Node.js" {9}
import { AirweaveSDKClient } from "@airweave/sdk";

const client = new AirweaveSDKClient({ apiKey: "YOUR_API_KEY" });

const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "payment failures",
    expandQuery: true,
  }
);
```
</CodeBlocks>



### Search Method

The search method determines how Airweave searches your data. Different methods balance semantic understanding and keyword precision. You can use AI to understand meaning, traditional keyword matching, or both.

**Parameter**: `retrieval_strategy`
- `hybrid` (default): Best of both worlds - finds results by meaning AND exact keywords
- `neural`: AI-powered search that understands what you mean, not just what you type
- `keyword`: Traditional search that looks for exact word matches

<CodeBlocks>
```bash title="cURL" {6}
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "authentication flow security vulnerabilities",
    "retrieval_strategy": "hybrid"
  }'
```

```python title="Python" {5}
results = await client.collections.search_advanced(
    "your-collection-id",
    {
        "query": "authentication flow security vulnerabilities",
        "retrieval_strategy": "hybrid"
    }
)
```

```javascript title="Node.js" {5}
const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "authentication flow security vulnerabilities",
    retrievalStrategy: "hybrid",
  }
);
```
</CodeBlocks>



### Filtering Results

Applies structured filters before search, ensuring only relevant subsets are scanned. Useful for large datasets or when results must match specific attributes like source, date, or status.

**Parameter**: `filter`

**Example 1: Filter by source**

<CodeBlocks>
```bash title="cURL" {5-10}
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "deployment issues",
    "filter": {
      "must": [{
        "key": "source_name",
        "match": {"value": "GitHub"}
      }]
    }
  }'
```

```python title="Python" {5-10}
results = await client.collections.search_advanced(
    "your-collection-id",
    {
        "query": "deployment issues",
        "filter": {
            "must": [{
                "key": "source_name",
                "match": {"value": "GitHub"}  # Case-sensitive!
            }]
        }
    }
)
```

```javascript title="Node.js" {5-10}
const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "deployment issues",
    filter: {
      must: [{
        key: "source_name",
        match: { value: "GitHub" }  // Case-sensitive!
      }]
    }
  }
);
```
</CodeBlocks>

**Example 2: Multiple filters**

<CodeBlocks>
```bash title="cURL"
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "customer feedback",
    "filter": {
      "must": [
        {
          "key": "source_name",
          "match": {"any": ["Zendesk", "Intercom", "Slack"]}
        },
        {
          "key": "created_at",
          "range": {
            "gte": "2024-01-01T00:00:00Z"
          }
        }
      ]
    }
  }'
```

```python title="Python"
from datetime import datetime, timezone, timedelta

results = await client.collections.search_advanced(
    "your-collection-id",
    {
        "query": "customer feedback",
        "filter": {
            "must": [
                {
                    "key": "source_name",
                    "match": {"any": ["Zendesk", "Intercom", "Slack"]}
                },
                {
                    "key": "created_at",
                    "range": {
                        "gte": (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
                    }
                }
            ]
        }
    }
)
```

```javascript title="Node.js"
const oneWeekAgo = new Date();
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);

const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "customer feedback",
    filter: {
      must: [
        {
          key: "source_name",
          match: { any: ["Zendesk", "Intercom", "Slack"] }
        },
        {
          key: "created_at",
          range: {
            gte: oneWeekAgo.toISOString()
          }
        }
      ]
    }
  }
);
```
</CodeBlocks>

**Example 3: Exclude results**

<CodeBlocks>
```bash title="cURL"
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "bug reports",
    "filter": {
      "must_not": [{
        "key": "status",
        "match": {"any": ["resolved", "closed", "done"]}
      }]
    }
  }'
```

```python title="Python"
results = await client.collections.search_advanced(
    "your-collection-id",
    {
        "query": "bug reports",
        "filter": {
            "must_not": [{
                "key": "status",
                "match": {"any": ["resolved", "closed", "done"]}
            }]
        }
    }
)
```

```javascript title="Node.js"
const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "bug reports",
    filter: {
      must_not: [{
        key: "status",
        match: { any: ["resolved", "closed", "done"] }
      }]
    }
  }
);
```
</CodeBlocks>

### Query Interpretation

<Warning>
This feature is currently in beta. It can occasionally filter too narrowly, so verify result counts.
</Warning>

Query interpretation allows Airweave to automatically extract structured filters from a natural language query. Instead of manually defining metadata filters, you can simply describe what you are looking for, and Airweave will translate that description into filter conditions.

This feature is useful when you want to let end users search in plain English, for example _"open GitHub issues from last week"_ or _"critical bugs reported this month"_. Airweave analyzes the query, identifies entities like dates, sources, or statuses, and applies them as filters.

**Parameter**: `interpret_filters` (boolean)
- `false` (default): You control all filters manually
- `true`: AI extracts filters from your natural language query

<CodeBlocks>
```bash title="cURL" {6}
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "open asana tickets from last week",
    "interpret_filters": true
  }'
```

```python title="Python" {4,11}
results = await client.collections.search_advanced(
    readable_id="your-collection-id",
    query="open asana tickets from last week",
    interpret_filters=True
)
# AI understands: Asana source, open status, last 7 days

results = await client.collections.search_advanced(
    readable_id="your-collection-id",
    query="critical bugs from GitHub this month",
    interpret_filters=True
)
```

```javascript title="Node.js" {5,13}
const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "open asana tickets from last week",
    interpretFilters: true
  }
);

const response2 = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "critical bugs from GitHub this month",
    interpretFilters: true
  }
);
```
</CodeBlocks>

### Temporal Relevance

<Tip>Learn more about this topic in our blogpost: [Deep Dive on Temporal Relevance ](https://airweave.ai/blog/temporal-relevance-explained).</Tip>

Temporal relevance adjusts the results ranking to prefer newer documents. This is valuable for time-sensitive data like messages, customer feedback, tickets, or news.

The scoring formula adjusts results based on age:

**S<sub>final</sub> = S<sub>similarity</sub> × (1 − β + β × d(t))**

where,
- **S<sub>final</sub>** = final relevance score
- **S<sub>similarity</sub>** = semantic similarity score
- **β** = recency bias parameter (0 to 1)
- **d(t)** = time decay factor (0 = oldest, 1 = newest).


**Parameter**: `temporal_relevance` (0.0 to 1.0)
- `0.3` (default): Slightly prefer newer content
- `0.0`: Don't care about dates, just find the best matches
- `1.0`: Heavily prioritize the newest content

<CodeBlocks>
```bash title="cURL" {6}
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "project updates",
    "temporal_relevance": 0.7
  }'
```

```python title="Python" {4}
results = await client.collections.search_advanced(
    readable_id="your-collection-id",
    query="project updates",
    temporal_relevance=0.7
)
```

```javascript title="Node.js" {5}
const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "project updates",
    temporalRelevance: 0.7,
  }
);
```
</CodeBlocks>

Use this when freshness matters. For example, prioritizing the latest bug reports or recent customer complaints over historical ones.

### Pagination

Control how many results you get and navigate through large result sets.

**Parameters**:
- `limit`: How many results to return (1-1000, default: 20)
- `offset`: How many results to skip (for pagination, default: 0)

<CodeBlocks>
```bash title="cURL"
# Simple search with pagination
curl -X GET 'https://api.airweave.ai/collections/your-collection-id/search?query=data%20retention%20policies&limit=50&offset=50' \
  -H 'x-api-key: YOUR_API_KEY'
```

```python title="Python" {4-5}
response = await client.collections.search_collection(
    readable_id="your-collection-id",
    query="data retention policies",
    limit=50,
    offset=50,  # Skip first 50
)
```

```javascript title="Node.js" {4-5}
const response = await client.collections.searchCollection({
  readableId: "your-collection-id",
  query: "data retention policies",
  limit: 50,
  offset: 50,
});
```
</CodeBlocks>

### AI Reranking

AI reranking takes the top set of results from the initial search and reorders them using a large language model. This improves accuracy in cases where keyword or semantic similarity alone might be misleading.

**Parameter**: `rerank` (boolean)
- `true` (default): AI reviews and reorders results for best relevance
- `false`: Skip reranking for faster results

<Warning>
Reranking adds about 10 seconds to your search. Turn it off if you need fast results.
</Warning>

<CodeBlocks>
```bash title="cURL" {6}
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "user authentication methods",
    "rerank": false
  }'
```

```python title="Python" {4}
results = await client.collections.search_advanced(
    readable_id="your-collection-id",
    query="user authentication methods",
    rerank=False
)
```

```javascript title="Node.js" {5}
const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "user authentication methods",
    rerank: false,
  }
);
```
</CodeBlocks>

### Generate AI Answers

Airweave can return either raw results or a synthesized answer. When enabled, a large language model generates a natural language response based on the top results, including sources when available.

**Parameter**: `generate_answer` (boolean)
- `true` (default): Generate an AI-synthesized answer from the top search results
- `false`: Return only raw results

<CodeBlocks>
```bash title="cURL" {6}
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "What are our customer refund policies?",
    "generate_answer": true
  }'
```

```python title="Python" {4}
results = await client.collections.search_advanced(
    readable_id="your-collection-id",
    query="What are our customer refund policies?",
    generate_answer=True
)
# Access: results.completion
```

```javascript title="Node.js" {5}
const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "What are our customer refund policies?",
    generateAnswer: true,
  }
);
// Access: response.completion
```
</CodeBlocks>

## Complete example

Here's everything together in one search using the new API:

<CodeBlocks>
```bash title="cURL"
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "customer feedback about pricing",
    "expand_query": true,
    "retrieval_strategy": "hybrid",
    "filter": {
      "must": [{
        "key": "source_name",
        "match": {"any": ["Zendesk", "Slack"]}
      }]
    },
    "temporal_relevance": 0.5,
    "rerank": true,
    "generate_answer": false,
    "limit": 50,
    "offset": 0
  }'
```

```python title="Python"
from airweave import AirweaveSDK
from datetime import datetime, timezone, timedelta

client = AirweaveSDK(api_key="YOUR_API_KEY")

results = await client.collections.search_advanced(
    readable_id="your-collection-id",
    query="customer feedback about pricing",
    expand_query=True,
    retrieval_strategy="hybrid",
    filter={
        "must": [{
            "key": "source_name",
            "match": {"any": ["Zendesk", "Slack"]}
        }]
    },
    temporal_relevance=0.5,
    rerank=True,
    generate_answer=False,
    limit=50,
    offset=0
)
```

```javascript title="Node.js"
import { AirweaveSDKClient } from "@airweave/sdk";

const client = new AirweaveSDKClient({ apiKey: "YOUR_API_KEY" });

const response = await client.collections.searchAdvanced(
  "your-collection-id",
  {
    query: "customer feedback about pricing",
    expandQuery: true,
    retrievalStrategy: "hybrid",
    filter: {
      must: [{
        key: "source_name",
        match: { any: ["Zendesk", "Slack"] }
      }]
    },
    temporalRelevance: 0.5,
    rerank: true,
    generateAnswer: false,
    limit: 50,
    offset: 0
  }
);
```
</CodeBlocks>

### Legacy API Example

If you're still using the legacy API, here's how the same query looks (deprecated):

<CodeBlocks>
```bash title="Legacy cURL (Deprecated)"
curl -X POST 'https://api.airweave.ai/collections/your-collection-id/search' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "customer feedback about pricing",
    "expansion_strategy": "auto",
    "search_method": "hybrid",
    "filter": {
      "must": [{
        "key": "source_name",
        "match": {"any": ["Zendesk", "Slack"]}
      }]
    },
    "recency_bias": 0.5,
    "enable_reranking": true,
    "response_type": "raw",
    "limit": 50,
    "offset": 0
  }'
# Response will include X-API-Deprecation header
```

```python title="Legacy Python (Deprecated)"
# Using old parameter names (still works but deprecated)
results = await client.collections.search_advanced(
    readable_id="your-collection-id",
    query="customer feedback about pricing",
    expansion_strategy="auto",  # ❌ Use expand_query instead
    search_method="hybrid",     # ❌ Use retrieval_strategy instead
    recency_bias=0.5,           # ❌ Use temporal_relevance instead
    enable_reranking=True,      # ❌ Use rerank instead
    response_type="raw",        # ❌ Use generate_answer instead
)
```
</CodeBlocks>

<Card title="Ready to search?" icon="rocket">
  Try these examples live in our [interactive API documentation](https://docs.airweave.ai/api-reference/collections/search-collections-readable-id-search-post). You can execute real searches and see responses instantly!
</Card>
